import { BookSource } from './defined/booksource';
import { BookStore } from './defined/bookstore';
import { TextToSpeechEngine } from './defined/ttsengine';
import { PluginInterface } from './defined/plugins';
import { PluginType } from './index';
import { Logger } from '../logger';
import { Chapter } from '../book/book';

/**
 * 测试结果
 */
export interface TestResult {
  testName: string;
  success: boolean;
  duration: number;
  error?: string;
  data?: any;
}

/**
 * 测试套件结果
 */
export interface TestSuiteResult {
  pluginId: string;
  pluginName: string;
  pluginType: PluginType;
  totalTests: number;
  passedTests: number;
  failedTests: number;
  duration: number;
  results: TestResult[];
}

/**
 * 插件测试框架
 */
export class PluginTestFramework {
  /**
   * 测试书源插件
   */
  static async testBookSource(
    plugin: PluginInterface,
    instance: BookSource,
    testConfig: {
      searchKeyword?: string;
      detailUrl?: string;
      chapter?: Chapter;
    } = {},
  ): Promise<TestSuiteResult> {
    const results: TestResult[] = [];
    const startTime = Date.now();

    // 测试搜索功能
    if (testConfig.searchKeyword) {
      const searchResult = await this.runTest(
        'search',
        async () => {
          const results = await instance.search(testConfig.searchKeyword!);
          if (!Array.isArray(results)) {
            throw new Error('Search should return an array');
          }
          if (results.length === 0) {
            throw new Error('Search returned no results');
          }
          return results;
        },
      );
      results.push(searchResult);
    }

    // 测试详情获取
    if (testConfig.detailUrl) {
      const detailResult = await this.runTest(
        'getDetail',
        async () => {
          const detail = await instance.getDetail(testConfig.detailUrl!);
          if (!detail || !detail.name) {
            throw new Error('Invalid detail response');
          }
          return detail;
        },
      );
      results.push(detailResult);
    }

    // 测试正文获取
    if (testConfig.chapter) {
      const contentResult = await this.runTest(
        'getTextContent',
        async () => {
          const content = await instance.getTextContent(testConfig.chapter!);
          if (!Array.isArray(content)) {
            throw new Error('getTextContent should return an array');
          }
          if (content.length === 0) {
            throw new Error('getTextContent returned empty content');
          }
          return content;
        },
      );
      results.push(contentResult);
    }

    return this.createTestSuiteResult(plugin, results, startTime);
  }

  /**
   * 测试书城插件
   */
  static async testBookStore(
    plugin: PluginInterface,
    instance: BookStore,
  ): Promise<TestSuiteResult> {
    const results: TestResult[] = [];
    const startTime = Date.now();

    // 测试配置获取
    const configResult = await this.runTest(
      'config',
      async () => {
        const config = instance.config;
        if (!config || typeof config !== 'object') {
          throw new Error('Invalid config object');
        }
        
        const keys = Object.keys(config);
        if (keys.length === 0) {
          throw new Error('Config object is empty');
        }
        
        // 测试第一个配置项
        const firstKey = keys[0];
        const configItem = instance.getConfigItem(firstKey);
        if (typeof configItem !== 'function') {
          throw new Error(`Config item ${firstKey} is not a function`);
        }
        
        const items = await configItem();
        if (!Array.isArray(items)) {
          throw new Error(`Config item ${firstKey} should return an array`);
        }
        
        return { keys, firstKeyItems: items };
      },
    );
    results.push(configResult);

    return this.createTestSuiteResult(plugin, results, startTime);
  }

  /**
   * 运行单个测试
   */
  private static async runTest(
    testName: string,
    testFunction: () => Promise<any>,
  ): Promise<TestResult> {
    const startTime = Date.now();
    
    try {
      const data = await testFunction();
      const duration = Date.now() - startTime;
      
      Logger.info(`Test ${testName} passed in ${duration}ms`);
      
      return {
        testName,
        success: true,
        duration,
        data,
      };
    } catch (error) {
      const duration = Date.now() - startTime;
      const errorMessage = error instanceof Error ? error.message : String(error);
      
      Logger.error(`Test ${testName} failed in ${duration}ms:`, errorMessage);
      
      return {
        testName,
        success: false,
        duration,
        error: errorMessage,
      };
    }
  }

  /**
   * 创建测试套件结果
   */
  private static createTestSuiteResult(
    plugin: PluginInterface,
    results: TestResult[],
    startTime: number,
  ): TestSuiteResult {
    const duration = Date.now() - startTime;
    const passedTests = results.filter(r => r.success).length;
    const failedTests = results.filter(r => !r.success).length;

    return {
      pluginId: plugin.ID,
      pluginName: plugin.NAME,
      pluginType: plugin.TYPE,
      totalTests: results.length,
      passedTests,
      failedTests,
      duration,
      results,
    };
  }
}